package com.ecut.xzh.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.ecut.xzh.constant.LengthConstant;
import com.ecut.xzh.constant.MessageConstant;
import com.ecut.xzh.dto.UserLoginDTO;
import com.ecut.xzh.dto.UserRegisterDTO;
import com.ecut.xzh.entity.User;
import com.ecut.xzh.exception.*;
import com.ecut.xzh.mapper.HabitsMapper;
import com.ecut.xzh.mapper.UserMapper;
import com.ecut.xzh.service.UserService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;

/**
 * @author XZH
 */
@Service
public class UserServiceImpl implements UserService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private HabitsMapper habitsMapper;

    /**
     * 用户登录
     *
     * @param userLoginDTO
     * @return
     */
    @Override
    public User login(UserLoginDTO userLoginDTO) {
        String number = userLoginDTO.getNumber();
        String password = userLoginDTO.getPassword();

        // 判断学号和密码是否为空
        if(StrUtil.isBlank(number) || StrUtil.isBlank(password)){
            throw new NumberOrPasswordIsNullException(MessageConstant.NUMBER_OR_PASSWORD_IS_NULL);
        }

        // 去数据库查询是否有这个学号
        User user = userMapper.getByNumber(number);

        if (user == null) {
            // 账号不存在
            throw new UserNotFoundException(MessageConstant.USER_NOT_FOUND);
        }

        String passwordMd5 = DigestUtils.md5DigestAsHex(password.getBytes());
        if (!passwordMd5.equals(user.getPassword())) {
            // 密码错误
            throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
        }

        // 一切外键约束在业务层中解决，这里为再次加强处理，查询在habits表中有没有这个用户的外键
        Long userId = user.getId();
        int count = habitsMapper.countByUserId(userId);

        // 如果没有这个外键，则插入
        if (count == 0) {
            habitsMapper.insert(userId);
        }

        // 将Id和学号传回去
        return user;
    }

    /**
     * 用户注册
     * @param userRegisterDTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void register(UserRegisterDTO userRegisterDTO) {
        String number = userRegisterDTO.getNumber();
        String password = userRegisterDTO.getPassword();
        String phone = userRegisterDTO.getPhone();

        // 判断学号、密码和手机号是否为空
        if(StrUtil.isBlank(number) || StrUtil.isBlank(password) || StrUtil.isBlank(phone)){
            throw new NumberOrPasswordOrPhoneIsNullExceptionException(MessageConstant.NUMBER_OR_PASSWORD_OR_PHONE_IS_NULL);
        }

        // 判断学号格式是否正确
        numberFormat(number);

        // 判断手机号格式是否正确
        String phoneFormat = "^(?:(?:\\+|00)86)?1(?:(?:3[\\d])|(?:4[5-7|9])|(?:5[0-3|5-9])|(?:6[5-7])|(?:7[0-8])|(?:8[\\d])|(?:9[1|8|9]))\\d{8}$";
        // 如果不符合
        if(!phone.matches(phoneFormat)){
            throw new PhoneException(MessageConstant.PHONE_ERROR);
        }

        // 去数据库查询是否有这个学号，判断学号是否已经存在
        User user = userMapper.getByNumber(number);
        if (user != null) {
            // 账号已存在
            throw new UserAlreadyRegisterException(MessageConstant.USER_ALREADY_REGISTER);
        }

        // 去数据库查询是否有这个手机号，判断手机号是否已经存在
        int count = userMapper.countByPhone(phone);
        if (count != 0) {
            // 手机号已存在
            throw new PhoneAlreadyRegisterException(MessageConstant.PHONE_ALREADY_REGISTER);
        }

        User userWithTime = new User();
        // 复制属性
        BeanUtil.copyProperties(userRegisterDTO, userWithTime);
        // 添加时间
        userWithTime.setCreateTime(LocalDateTime.now());
        userWithTime.setUpdateTime(LocalDateTime.now());
        // 密码加密
        String passwordMd5 = DigestUtils.md5DigestAsHex(password.getBytes());
        // 更新未加密密码
        userWithTime.setPassword(passwordMd5);

        // 新增用户信息和对应的习惯表信息
        userMapper.insert(userWithTime);

        // 查询刚刚存进去的学生id
        user= userMapper.getByNumber(number);
        // 新增学生习惯信息，只添加一个student_id
        habitsMapper.insert(user.getId());

    }

    /**
     * 学号格式
     * 用此方法前需确保number不为null
     */
    private void numberFormat(String number) {
        // 获取当前年份
        int year = LocalDateTime.now().getYear();
        // 获取前四位
        String startStr = StrUtil.sub(number, 0, 4);
        int start = Integer.parseInt(startStr);

        if(number.length() != LengthConstant.NUMBER){
            throw new NumberException(MessageConstant.NUMBER_ERROR);
        }

        if(start < LengthConstant.ECUT_START || start > year){
            throw new NumberException(MessageConstant.NUMBER_ERROR);
        }
    }
}


